package com.yang.qqservice.service;

import com.yang.common.Message;
import com.yang.common.MessageType;
import com.yang.common.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;

/**
 * @Description: 服务器, 在9999端口监听, 等待客户的连接, 并保持通信
 * @Author: YANG QIANG
 * @Time: 2022-12-20 21:20
 */
public class QQServer {
    private ServerSocket serverSocket;
    // 创建一个集合存放合法的用户
    private static HashMap<String, User> validUsers = new HashMap<>();

    static {
        validUsers.put("100", new User("100", "123456"));
        validUsers.put("200", new User("200", "123456"));
        validUsers.put("至尊宝", new User("至尊宝", "123456"));
        validUsers.put("紫霞仙子", new User("紫霞仙子", "123456"));
    }

    // 验证用户是否有效的方法
    private boolean checkUser(String userId, String pwd){
        User user = validUsers.get(userId);
        if (user == null){
            return false;
        }
        if (!user.getPwd().equals(pwd)){
            return false;
        }
        return true;
    }


    public QQServer() {
        try {
            System.out.println("服务端在9999端口监听");

            // 启动一个推送新闻的线程
            new Thread(new SendNewsToAllService()).start();

            serverSocket = new ServerSocket(9999);

            // 监听是一直监听的
            while (true){
                Socket socket = serverSocket.accept();
                // 读取客户端传过来的登录user对象
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                User user = (User)ois.readObject();

                // 创建一个message, 用于回复客户端
                Message message = new Message();

                // 得到一个对象输出流
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

                // 去集合验证用户是否存在
                if (checkUser(user.getUserId(), user.getPwd())){
                    System.out.println("用户[" + user.getUserId() + "]  密码[" + user.getPwd() + "] 登录成功..");
                    message.setMessageType(MessageType.MESSAGE_LOGIN_SUCCEED);
                    oos.writeObject(message);
                    // 登录成功, 创建一个线程和客户端保持通信, 该线程需要持有socket
                    ServerConnectClientThread connectClientThread = new ServerConnectClientThread(socket, user.getUserId());
                    connectClientThread.start();
                    // 放到线程集合中
                    ManageClientThread.addServerConnectClientThread(user.getUserId(), connectClientThread);

                    // 有用户的离线消息就推送给用户
                    List<Message> offLineHm = ManageClientThread.getOffLineHm(user.getUserId());
                    if (offLineHm != null && offLineHm.size() > 0){
                        for (Message message1 : offLineHm) {
                            // 离线私聊消息
                            if (message1.getMessageType().equals(MessageType.MESSAGE_C0MM_MES)){
                                // 根据message获取需要发送给的userId的对应的线程
                                ServerConnectClientThread serverConnectClientThread = ManageClientThread.getServerConnectClientThread(message1.getGetter());
                                // 发送给接收人
                                ObjectOutputStream oos1 = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                                oos1.writeObject(message1);
                            }
                        }

                        ManageClientThread.removeOffLineHm(user.getUserId());
                    }

                }else {
                    System.out.println("用户[" + user.getUserId() + "]  密码[" + user.getPwd() + "] 登录失败..");
                    message.setMessageType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                    socket.close();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
